package router

import (
	"errors"
	//"fmt"
	"time"

	"gitee.com/liukexing/isrn/model"
)

const ()

var ()

func TickCheck(data *model.Trans, key *RemoteCyprto) (*model.TickInfo, error) {
	var packdata []byte
	if key != nil {
		data, err := key.Decrypt(data.Data)
		if err != nil {
			return nil, err
		}
		packdata = data
	} else {
		packdata = data.Data
	}
	tickinfo := &model.TickInfo{}
	if _, err := tickinfo.GetData(packdata); err != nil {
		return nil, err
	}
	//data lengh
	if len(packdata) != data.PackInfo.Lengh {
		return nil, errors.New("Data Length Check Failed")
	}
	//Receiver
	if data.PackInfo.Receiver != nodeid {
		return nil, errors.New("Receiver Check Failed")
	}
	//NodeId and Sender
	if tickinfo.NodeId != data.PackInfo.Sender {
		return nil, errors.New("NodeId and Sender Check Failed")
	}
	//PackInfo Sign
	packinfook, err := key.Verify(packdata, data.PackInfo.Sign)
	if err != nil {
		return nil, err
	}
	if !packinfook {
		return nil, errors.New("PackInfo Sign Check Failed")
	}
	//Trans Sign
	transok, err := key.Verify(data.Data, data.Sign)
	if err != nil {
		return nil, err
	}
	if !transok {
		return nil, errors.New("Trans Sign Check Failed")
	}

	return tickinfo, nil
}

func TickController(data *model.Trans, isEncrypt bool, sender *ConnectInfo) error {
	tickinfo, err := TickCheck(data, getRemoteCyprto(isEncrypt, sender))
	if err != nil {
		return err
	}
	sender.LastTick = time.Now()
	//fmt.Println(sender.NodeId, time.Since(tickinfo.Stamp))

	if tickinfo.Sign == "Request" {
		return sendTickResponse(sender)
	}
	return nil
}

func sendTickRequest(conn *ConnectInfo) error {
	tickinfo := &model.TickInfo{}
	tickinfo.Sign = "Request"
	tickinfo.NodeId = nodeid
	tickinfo.Stamp = time.Now()

	data, err := tickinfo.GetByte()
	if err != nil {
		return err
	}

	s, err := conn.RCyprto.Sign(data)
	if err != nil {
		return err
	}
	dataEn, err := conn.RCyprto.Encrypt(data)
	if err != nil {
		return err
	}
	sn, err := conn.RCyprto.Sign(dataEn)
	if err != nil {
		return err
	}
	trans := &model.Trans{}
	trans.CreatPackInfo(dataEn, s, nodeid, conn.NodeId)
	trans.PackInfo.Lengh = len(data)
	trans.Sign = sn
	trans.PackType = model.Tick

	msg, err := getTransByte(trans, true, &conn.RCyprto)
	if err != nil {
		return err
	}
	conn.SendMsg(msg)
	return nil
}

func sendTickResponse(conn *ConnectInfo) error {
	tickinfo := &model.TickInfo{}
	tickinfo.Sign = "Response"
	tickinfo.NodeId = nodeid
	tickinfo.Stamp = time.Now()

	data, err := tickinfo.GetByte()
	if err != nil {
		return err
	}

	s, err := conn.RCyprto.Sign(data)
	if err != nil {
		return err
	}
	dataEn, err := conn.RCyprto.Encrypt(data)
	if err != nil {
		return err
	}
	sn, err := conn.RCyprto.Sign(dataEn)
	if err != nil {
		return err
	}
	trans := &model.Trans{}
	trans.CreatPackInfo(dataEn, s, nodeid, conn.NodeId)
	trans.PackInfo.Lengh = len(data)
	trans.Sign = sn
	trans.PackType = model.Tick

	msg, err := getTransByte(trans, true, &conn.RCyprto)
	if err != nil {
		return err
	}
	conn.SendMsg(msg)
	return nil
}
